package cn.example.util.toolkit;

import cn.example.util.ToolFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Date;
import java.util.List;

/**
 * 文件上传工具
 * Created by WuYB on 2017/6/9.
 */
public class UploadUtil {

    private static final Logger log = LoggerFactory.getLogger(UploadUtil.class);

    private static class SingletonHolder {
        private static final UploadUtil INSTANCE = new UploadUtil();
    }

    private UploadUtil() {
    }

    public static UploadUtil getInstance() {
        return SingletonHolder.INSTANCE;
    }


    /**
     * 多文件上传
     *
     * @param files   上传文件数组
     * @param root    文件根目录
     * @param secPath 二级目录
     * @return String
     */
    public String fileUpload(List<MultipartFile> files, String root, String secPath) {
        StringBuilder paths = new StringBuilder();
        if (files != null && files.size() > 0) {
            for (MultipartFile z : files) {
                if (z != null && !z.isEmpty()) {
                    paths.append(saveUpload(z, root, secPath));
                    paths.append(";");
                } else {
                    log.error("文件数组中存在空的文件！");
                }
            }
            return paths.deleteCharAt(paths.length() - 1).toString();
        }
        log.error("上传文件为空！");
        return null;
    }

    /**
     * 单文件上传
     *
     * @param file    上传文件
     * @param root    文件根目录
     * @param secPath 二级目录
     * @return String
     */
    public String fileUpload(MultipartFile file, String root, String secPath) {
        if (file != null && !file.isEmpty()) {
            return saveUpload(file, root, secPath);
        }
        log.error("上传文件为空！");
        return null;
    }

    /**
     * 保存上传文件
     *
     * @param file    文件
     * @param root    文件根目录
     * @param secPath 二级目录
     * @return 相对路径
     */
    private String saveUpload(MultipartFile file, String root, String secPath) {
        String dir = secPath + "/" + ToolFactory.getDateUtil().date2Str(new Date(), "yyyyMMdd") + "/";
        File fileDir = new File(root, dir);
        if (!fileDir.exists()) {
            fileDir.mkdirs();
        }
        String fName = filterUploadFileName(file.getOriginalFilename());
        File target = new File(fileDir, fName);
        try {
            file.transferTo(target);
            return "/" + dir + fName;
        } catch (IOException e) {
            log.error("上传文件保存到磁盘异常：", e);
            return null;
        }
    }

    /**
     * 上传文件后缀名过滤
     *
     * @param filename 原文件名
     * @return String
     */
    private String filterUploadFileName(String filename) {
        String name = filename.substring(0, filename.lastIndexOf(".") + 1);
        String suffix = filename.substring(filename.lastIndexOf(".") + 1, filename.length()).toLowerCase();
        return name + suffix;
    }

    /**
     * 文件下载（流）
     *
     * @param bytes    文件（字节型数组）
     * @param fileName 文件名
     * @param response HttpServletResponse
     */
    public void fileDownload(byte[] bytes, String fileName, HttpServletRequest request, HttpServletResponse response) {
        try {
            fileName = convertFileName(fileName, request);
            response.setContentType("application/octet-stream;charset=UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=\"" + fileName + "\"");
            response.flushBuffer();
            response.getOutputStream().write(bytes);
        } catch (IOException e) {
            log.error("下载文件流异常！", e);
        }
    }


    /**
     * 下载文件名处理
     *
     * @param filename 文件名
     * @param request  HttpServletRequest
     * @return 转码后的文件名
     */
    public String convertFileName(String filename, HttpServletRequest request) {
        try {
            NullUtil nullUtil = ToolFactory.getNullUtil();
            String agent = request.getHeader("USER-AGENT");
            if (!nullUtil.isNull(agent) && !nullUtil.isNull(filename)) {
                agent = agent.toUpperCase();
                if (agent.contains("MSIE") || agent.contains("TRIDENT")) {// ie
                    filename = URLEncoder.encode(filename, "UTF-8");
                } else {// 火狐,chrome等
                    filename = new String(filename.getBytes("UTF-8"), "iso-8859-1");
                }
                return filename;
            }
            return null;
        } catch (UnsupportedEncodingException e) {
            log.error("文件名转换失败", e);
            return null;
        }
    }

}
